package cn.zzuzhm.spring.aop;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class CalculatorAspect {
    
	/**
	 * 
	 * @Title: declareJoinPoint   
	 * @Description: 用于声明切入点，方法体通常是空的
	 * @param:       
	 * @return: void      
	 * @throws
	 */
	@Pointcut(value="execution (public int cn.zzuzhm.spring.aop.Calculator.*(int, int))")
	public void declareJoinPoint(){}
	
	/**
	 * 
	 * @Title: beforeMethod   
	 * @Description: 前置通知 ,执行方法前开始执行
	 * @param: @param joinPoint      
	 * @return: void      
	 * @throws
	 */
	@Before("declareJoinPoint()")
	public void beforeMethod(JoinPoint joinPoint){
		String methodName = joinPoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinPoint.getArgs()); 
		System.out.println("The method " + methodName + " begin with " + args);
	}
	
	/**
	 * 
	 * @Title: afterMethod   
	 * @Description: 后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 
	 *               下面的后置通知记录了方法的终止. 
	 * @param: @param joinPoint      
	 * @return: void      
	 * @throws
	 */
	@After(value = "declareJoinPoint()")
	public void afterMethod(JoinPoint joinPoint){
		String methodName = joinPoint.getSignature().getName();
		System.out.println("The method " + methodName + " ends");
	}
	
	/**
	 * 
	 * @Title: afterReturn   
	 * @Description: 无论连接点是正常返回还是抛出异常, 后置通知都会执行. 如果只想在连接点返回的时候记录日志, 
	 *               应使用返回通知代替后置通知.在返回通知中, 只要将 returning 属性添加到 @AfterReturning 注解中,
	 *               就可以访问连接点的返回值. 该属性的值即为用来传入返回值的参数名称.  
	 * @param: @param joinPoint
	 * @param: @param result      
	 * @return: void      
	 * @throws
	 */
	@AfterReturning(value = "declareJoinPoint()",returning="result")
	public void afterReturn(JoinPoint joinPoint,Object result){
		String methodName = joinPoint.getSignature().getName();
		System.out.println("The method " + methodName + " ends with " + result);
	}
	
	/**
	 * 
	 * @Title: afterThrow   
	 * @Description: 只在连接点抛出异常时才执行异常通知,将 throwing 属性添加到 @AfterThrowing 注解中, 
	 *               也可以访问连接点抛出的异常. Throwable 是所有错误和异常类的超类.
	 *               所以在异常通知方法可以捕获到任何错误和异常.
	 * @param: @param joinPoint
	 * @param: @param e      
	 * @return: void      
	 * @throws
	 */
	@AfterThrowing(value = "execution (public int cn.zzuzhm.spring.aop.Calculator.*(int, int))",throwing = "e")
	public void afterThrow(JoinPoint joinPoint,Exception e){
		String methodName = joinPoint.getSignature().getName();
		System.out.println("An exception " + e + "has been throwing in" + methodName + "()");
	}
}
